﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using RATSharp.Model;
using System.Collections.Generic;
using RATSharp.Rest;
using System.Threading.Tasks;
using System.Runtime.Serialization;

namespace RATSharpW7.ViewModel
{
    [DataContract]
    public class ReservationPeriodsViewModel : ReservationViewModel
    {
        private Dictionary<int, bool> periodStateDictionary = new Dictionary<int,bool>();

        /// <summary>
        /// load all periods from single reservation
        /// </summary>
        /// <param name="id"></param>
        public void loadPeriods(int id)
        {
            Task<Reservations> task = RestService.getInstance().getReservationById(id);
            notifyChangeModel(task);
        }


        protected override void extractReservations(Reservations resList)
        {
            base.extractReservations(resList);
            //save previous state of periods so after user submit changes we can sent only
            //changed periods, not all of them
            foreach (period period in DataSource)
            {
                periodStateDictionary.Add(period.id.Value, period.Valid);
            }
        }

        //compare data model with previous period state and save changes
        public void saveChanges(EventHandler handler) 
        {
            PeriodRunner runner = new PeriodRunner(DataSource.GetEnumerator(), periodStateDictionary, handler);
            runner.start();
        }


        /// <summary>
        /// Implementation of "async iterator" pattern
        /// Because whole communication is async and server does not provide
        /// batch update over period collection we need to go
        /// through whole collection and update period individually
        /// </summary>
        private class PeriodRunner
        {

             IEnumerator<period> iterator;
             bool started = false;
             private Dictionary<int, bool> periodStateDictionary;
             EventHandler runnerComplete;

            public PeriodRunner(IEnumerator<period> iterator, Dictionary<int, bool> periodStateDictionary, EventHandler runnerComplete)
            {
                this.periodStateDictionary = periodStateDictionary;
                this.iterator = iterator;
                this.runnerComplete = runnerComplete;
            }

            public void start()
            {
                if (!started)
                {
                    started = true;
                    next();
                }
            }

            private void next()
            {
                while (iterator.MoveNext())
                {
                    bool previousState;
                    periodStateDictionary.TryGetValue(iterator.Current.id.Value, out previousState);
                    if (iterator.Current.Valid != previousState)
                    {
                        Task<Reservations> task =  RestService.getInstance().modifyPeriod(iterator.Current.id.Value, iterator.Current.Valid);
                        handleFinishedTask(task);
                        return;
                    }

                }

                Deployment.Current.Dispatcher.BeginInvoke(() =>
                {
                    notifyPeriodRunnerComplete();
                });
            }

            private void notifyPeriodRunnerComplete()
            {
                runnerComplete(this, new EventArgs());
            }

            private void handleFinishedTask(Task<Reservations> task)
            {
                task.ContinueWith(t =>
                {
                   next();
                });
            }
        }
    }
    }
